package com.lv.aop.advice;

import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.lv.aop.Log;
import com.lv.entity.LogEntity;

import com.lv.mapper.LogMapper;
import org.apache.log4j.Logger;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;

import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;


import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;



/**
 * Created with IntelliJ IDEA.
 * <p>
 *
 * </p>
 *
 * @Author: 凉薄
 * @Date: 2022/02/27/12:18
 * @Description:
 */
@Aspect
@Component
public class LogAdvice {
    @Autowired
    LogMapper logMapper;
    private Logger logger=Logger.getLogger(LogAdvice.class);
    @Pointcut("@annotation(com.lv.aop.Log)")
    public  void point(){
    }

    @After("point()")
    public void after(JoinPoint joinPoint){
        LogEntity logEntity=new LogEntity();
        HttpServletRequest request;
        //获取请求的ip
        ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if(servletRequestAttributes!=null){
            request = servletRequestAttributes.getRequest();
            if(request!=null){

                String remoteHost = getRemoteHost(request);
                logEntity.setIpAddress(remoteHost);
                logger.info("请求地址："+remoteHost);
            }
        }

        //获取用户名
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        if(authentication==null) {
            logEntity.setUsername("未登录用户");
        }else{
            logEntity.setUsername(authentication.getName());
        }

        //获取方法描述
        String targetName = joinPoint.getTarget().getClass().getName();
        String methodName = joinPoint.getSignature().getName();
        Object[] args = joinPoint.getArgs();
        Method[] methods = new Method[0];
        try {
            methods = Class.forName(targetName).getMethods();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        StringBuffer params=new StringBuffer();
        for (Method method : methods) {
            if(method.getName().equals(methodName)&&method.getParameterCount()==args.length){
                //获取描述
                String value = method.getAnnotation(Log.class).value();
                logEntity.setDescription(value);
                //获取参数
                Parameter[] parameters = method.getParameters();
                for (int i = 0; i < parameters.length; i++) {
                    params.append(parameters[i].getName()+"="+ JSON.toJSONString(args[i]) +',');
                }
                break;
            }
        }
       logEntity.setParams(String.valueOf(params));
        logger.info(logEntity);
         logMapper.insert(logEntity);
    }
    //根据request获取请求的ip
    private String getRemoteHost(HttpServletRequest request) {
        String ip = request.getHeader("x-forwarded-for");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        return "0:0:0:0:0:0:0:1".equals(ip) ? "127.0.0.1" : ip;
    }

    @AfterThrowing(pointcut = "point()",throwing = "e")
    public void afterException(JoinPoint joinPoint,Throwable e){
        LogEntity logEntity=new LogEntity();
        HttpServletRequest request=null;
        HttpServletResponse response=null;
        //获取请求的ip
        ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if(servletRequestAttributes!=null){
            request = servletRequestAttributes.getRequest();
            response=servletRequestAttributes.getResponse();
            if(request!=null){

                String remoteHost = getRemoteHost(request);
                logEntity.setIpAddress(remoteHost);
                logger.info("请求地址："+remoteHost);
            }
        }

        //获取用户名
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        if(authentication==null) {
            logEntity.setUsername("未登录用户");
        }else{
            logEntity.setUsername(authentication.getName());
        }

        //获取方法描述和参数
        String targetName = joinPoint.getTarget().getClass().getName();
        String methodName = joinPoint.getSignature().getName();
        Object[] args = joinPoint.getArgs();
        Method[] methods = new Method[0];
        try {
            methods = Class.forName(targetName).getMethods();
        } catch (ClassNotFoundException ex) {
            ex.printStackTrace();
        }
        String params="";
        for (Method method : methods) {
            if(method.getName().equals(methodName)&&method.getParameterCount()==args.length){
                //获取描述
                String value = method.getAnnotation(Log.class).value();
                logEntity.setDescription(value);
                //获取参数
                Parameter[] parameters = method.getParameters();
                for (Parameter parameter : parameters) {
                    params=params+parameter.getName()+":"+request.getParameter(parameter.getName())+",";
                }
                logEntity.setParams(params);
                break;
            }
        }
        logEntity.setExceptionCode(e.getClass().getName());
        logEntity.setExceptionDes(e.getMessage());
        logger.info(logEntity);
        logMapper.insert(logEntity);
    }
}
